<template>
  <view class="schedule-container">
    <!-- 人员池 -->
    <view class="staff-pool">
      <view class="pool-header">
        <text>人员池</text>
      </view>
      <view class="staff-list">
        <view
          v-for="(staff, index) in staffList"
          :key="index"
          class="staff-item"
        >
          <checkbox :checked="staff.selected" @tap="toggleStaff(index)" />
          <text>{{ staff.name }}</text>
          <text class="delete" @tap="removeStaff(index)">×</text>
        </view>
      </view>
      <view class="add-staff">
        <input
          v-model="newStaffName"
          type="text"
          placeholder="输入姓名"
          class="staff-input"
          placeholder-class="input-placeholder"
        />
        <button @tap="addStaff" class="btn-add">添加</button>
      </view>
    </view>

    <!-- 排班设置 -->
    <view class="schedule-settings">
      <view class="settings-header">
        <text>排班设置</text>
        <view class="settings-actions">
          <button @tap="resetSettings" class="btn-action">重置设置</button>
          <button @tap="exportSchedule" class="btn-action">导出排班</button>
          <!-- <button @tap="importSchedule" class="btn-action">导入排班</button> -->
        </view>
      </view>

      <view class="setting-item">
        <text class="setting-label">排班月份：</text>
        <view class="setting-value">
          <picker
            mode="date"
            fields="month"
            :value="currentMonth"
            @change="onMonthChange"
          >
            <view class="picker">{{ currentMonth }}</view>
          </picker>
        </view>
      </view>
    </view>

    <!-- 员工偏好设置 -->
    <button @tap="showPreferences = !showPreferences" class="btn-toggle">
      {{ showPreferences ? "收起" : "展开" }}员工班次偏好设置
      <text class="toggle-icon">{{ showPreferences ? "▼" : "▲" }}</text>
    </button>
    <view
      class="staff-preferences"
      v-if="selectedStaff.length > 0 && showPreferences"
    >
      <view class="preferences-header">
        <view class="preferences-title">
          <text class="title-text">员工班次偏好设置</text>
          <text class="preferences-tip">（正数表示多上，负数表示少上）</text>
        </view>
      </view>
      <view class="preferences-list" v-show="showPreferences">
        <view
          v-for="staff in selectedStaff"
          :key="staff.name"
          class="preference-item"
        >
          <text class="staff-name">{{ staff.name }}</text>
          <view class="shift-preferences">
            <view class="shift-row">
              <view class="shift-preference-item">
                <text class="shift-label">白班</text>
                <view class="stepper">
                  <button
                    class="stepper-btn minus"
                    @tap="adjustShiftPreference(staff.name, 'WHITE', -1)"
                  >
                    -
                  </button>
                  <text
                    class="stepper-value"
                    :class="{
                      'has-value':
                        getShiftPreference(staff.name, 'WHITE') !== 0,
                    }"
                  >
                    {{ getShiftPreference(staff.name, "WHITE") }}
                  </text>
                  <button
                    class="stepper-btn plus"
                    @tap="adjustShiftPreference(staff.name, 'WHITE', 1)"
                  >
                    +
                  </button>
                </view>
              </view>
              <view class="shift-preference-item">
                <text class="shift-label">早班</text>
                <view class="stepper">
                  <button
                    class="stepper-btn minus"
                    @tap="adjustShiftPreference(staff.name, 'EARLY_NIGHT', -1)"
                  >
                    -
                  </button>
                  <text
                    class="stepper-value"
                    :class="{
                      'has-value':
                        getShiftPreference(staff.name, 'EARLY_NIGHT') !== 0,
                    }"
                  >
                    {{ getShiftPreference(staff.name, "EARLY_NIGHT") }}
                  </text>
                  <button
                    class="stepper-btn plus"
                    @tap="adjustShiftPreference(staff.name, 'EARLY_NIGHT', 1)"
                  >
                    +
                  </button>
                </view>
              </view>
            </view>
            <view class="shift-row">
              <view class="shift-preference-item">
                <text class="shift-label">休息</text>
                <view class="stepper">
                  <button
                    class="stepper-btn minus"
                    @tap="adjustShiftPreference(staff.name, 'REST', -1)"
                  >
                    -
                  </button>
                  <text
                    class="stepper-value"
                    :class="{
                      'has-value': getShiftPreference(staff.name, 'REST') !== 0,
                    }"
                  >
                    {{ getShiftPreference(staff.name, "REST") }}
                  </text>
                  <button
                    class="stepper-btn plus"
                    @tap="adjustShiftPreference(staff.name, 'REST', 1)"
                  >
                    +
                  </button>
                </view>
              </view>
              <view class="shift-preference-item">
                <text class="shift-label">指定休息日</text>
                <view class="rest-days-container">
                  <view class="rest-days-list">
                    <view
                      v-for="(date, index) in getRestDayPreference(staff.name)"
                      :key="index"
                      class="rest-day-item"
                    >
                      <text>{{ date }}</text>
                      <text
                        class="delete-rest-day"
                        @tap="clearRestDayPreference(staff.name, date)"
                        >×</text
                      >
                    </view>
                  </view>
                  <view class="rest-day-picker">
                    <picker
                      mode="date"
                      :value="currentMonth + '-01'"
                      @change="
                        (e) => setRestDayPreference(staff.name, e.detail.value)
                      "
                    >
                      <view class="picker-value"> 点击添加休息日 </view>
                    </picker>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 排班表格 -->
    <view class="schedule-table">
      <view class="table-tip">双击表格单元格可以修改班次</view>
      <view class="table-header">
        <view class="header-cell">姓名</view>
        <view v-for="day in daysInMonth" :key="day" class="day-cell">
          {{ day }}
        </view>
        <view class="summary-cell">白班</view>
        <view class="summary-cell">早班</view>
        <view class="summary-cell">休息</view>
        <view class="summary-cell remark-cell">备注</view>
      </view>
      <view v-for="staff in selectedStaff" :key="staff.name" class="table-row">
        <view class="name-cell">{{ staff.name }}</view>
        <view
          v-for="day in daysInMonth"
          :key="day"
          class="schedule-cell"
          :class="getShiftClass(staff.name, day)"
          @tap="toggleShift(staff.name, day)"
        >
          {{ getShiftText(staff.name, day) }}
        </view>
        <view class="summary-cell">{{
          getShiftCount(staff.name, "WHITE")
        }}</view>
        <view class="summary-cell">{{
          getShiftCount(staff.name, "EARLY_NIGHT")
        }}</view>
        <view class="summary-cell">{{ getRestDaysCount(staff.name) }}</view>
        <view class="summary-cell remark-cell">{{
          getShiftRemark(staff.name)
        }}</view>
      </view>
    </view>

    <button @tap="generateSchedule" class="btn-generate">生成排班表</button>
  </view>
  <canvas
    canvas-id="scheduleCanvas"
    style="position: absolute; left: -9999px; width: 3000px; height: 2000px"
  ></canvas>
</template>

<script>
import * as XLSX from "xlsx";
import html2canvas from "html2canvas";

export default {
  data() {
    return {
      staffList: [],
      newStaffName: "",
      currentMonth: "",
      schedule: {},
      allSelected: true,
      showPreferences: false,
      lastTapTime: 0,
      shiftTypes: {
        WHITE: "白",
        EARLY_NIGHT: "早",
        NIGHT: "晚",
      },
      settings: {
        shiftPreferences: {},
        restDayPreferences: {},
      },
    };
  },
  computed: {
    selectedStaff() {
      return this.staffList.filter((staff) => staff.selected);
    },
    daysInMonth() {
      const [year, month] = this.currentMonth.split("-");
      return new Date(year, month, 0).getDate();
    },
  },
  watch: {
    staffList: {
      handler(newVal) {
        uni.setStorageSync("staffList", JSON.stringify(newVal));
      },
      deep: true,
    },
    schedule: {
      handler(newVal) {
        uni.setStorageSync(
          "schedule_" + this.currentMonth,
          JSON.stringify(newVal),
        );
      },
      deep: true,
    },
    settings: {
      handler(newVal) {
        uni.setStorageSync("schedule_settings", JSON.stringify(newVal));
      },
      deep: true,
    },
  },
  created() {
    const now = new Date();
    this.currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;

    // 从本地存储加载数据
    this.loadStoredData();
  },
  methods: {
    loadStoredData() {
      // 加载员工列表
      const savedStaffList = uni.getStorageSync("staffList");
      if (savedStaffList) {
        this.staffList = JSON.parse(savedStaffList);
      } else {
        // 默认员工列表
        this.staffList = [
          { name: "郭卫强", selected: true },
          { name: "王鑫", selected: true },
          { name: "吕进", selected: true },
          { name: "王健鹏", selected: true },
          { name: "郭卫超", selected: true },
          { name: "陈克帅", selected: true },
          { name: "张卫红", selected: true },
        ];
      }

      // 加载设置
      const savedSettings = uni.getStorageSync("schedule_settings");
      if (savedSettings) {
        const settings = JSON.parse(savedSettings);
        this.settings = {
          ...this.settings,
          ...settings,
        };
      }

      // 加载已保存的排班表
      const savedSchedule = uni.getStorageSync("schedule_" + this.currentMonth);
      if (savedSchedule) {
        this.schedule = JSON.parse(savedSchedule);
      }
    },

    // 重置所有设置到默认值
    resetSettings() {
      uni.showModal({
        title: "确认重置",
        content: "是否要将所有设置恢复到默认值？",
        success: (res) => {
          if (res.confirm) {
            this.settings = {
              shiftPreferences: {},
              restDayPreferences: {},
            };
            uni.showToast({
              title: "设置已重置",
              icon: "success",
            });
          }
        },
      });
    },

    // 导出为图片
    async exportAsImage() {
      try {
        // #ifdef H5
        const element = document.querySelector(".schedule-table");

        // 获取表格的实际宽度
        const tableWidth = element.scrollWidth;
        const tableHeight = element.scrollHeight;

        // 临时调整容器样式以显示完整内容
        const originalStyle = {
          width: element.style.width,
          height: element.style.height,
          position: element.style.position,
          overflow: element.style.overflow,
        };

        element.style.width = tableWidth + "px";
        element.style.height = tableHeight + "px";
        element.style.position = "relative";
        element.style.overflow = "visible";

        const canvas = await html2canvas(element, {
          backgroundColor: "#ffffff",
          scale: 2,
          logging: false,
          useCORS: true,
          width: tableWidth,
          height: tableHeight,
          windowWidth: tableWidth,
          windowHeight: tableHeight,
        });

        // 恢复原始样式
        element.style.width = originalStyle.width;
        element.style.height = originalStyle.height;
        element.style.position = originalStyle.position;
        element.style.overflow = originalStyle.overflow;

        const link = document.createElement("a");
        link.download = `排班表_${this.currentMonth}.png`;
        link.href = canvas.toDataURL("image/png");
        link.click();
        // #endif

        // #ifdef MP-WEIXIN
        const query = uni.createSelectorQuery();
        query
          .select(".schedule-table")
          .boundingClientRect(async (data) => {
            // 计算画布尺寸
            const cellWidth = 60; // 日期单元格宽度
            const cellHeight = 40; // 单元格高度
            const nameWidth = 80; // 姓名列宽度
            const summaryWidth = 60; // 统计列宽度
            const remarkWidth = 120; // 备注列宽度

            // 计算总宽度和高度
            const totalWidth =
              nameWidth +
              this.daysInMonth * cellWidth +
              summaryWidth * 3 +
              remarkWidth;
            const totalHeight = (this.selectedStaff.length + 1) * cellHeight;

            const canvas = uni.createCanvasContext("scheduleCanvas");

            // 设置背景色
            canvas.fillStyle = "#ffffff";
            canvas.fillRect(0, 0, totalWidth, totalHeight);

            // 绘制表格线
            canvas.strokeStyle = "#dddddd";
            canvas.lineWidth = 1;

            // 绘制横线
            for (let i = 0; i <= this.selectedStaff.length + 1; i++) {
              canvas.beginPath();
              canvas.moveTo(0, i * cellHeight);
              canvas.lineTo(totalWidth, i * cellHeight);
              canvas.stroke();
            }

            // 绘制竖线
            let currentX = 0;
            // 姓名列
            canvas.beginPath();
            canvas.moveTo(currentX, 0);
            canvas.lineTo(currentX, totalHeight);
            canvas.stroke();
            currentX += nameWidth;

            // 日期列
            for (let i = 0; i <= this.daysInMonth; i++) {
              canvas.beginPath();
              canvas.moveTo(currentX, 0);
              canvas.lineTo(currentX, totalHeight);
              canvas.stroke();
              currentX += cellWidth;
            }

            // 统计列和备注列
            for (let i = 0; i < 4; i++) {
              canvas.beginPath();
              canvas.moveTo(currentX, 0);
              canvas.lineTo(currentX, totalHeight);
              canvas.stroke();
              currentX += i === 3 ? remarkWidth : summaryWidth;
            }

            // 设置文字样式
            canvas.fillStyle = "#333333";
            canvas.font = "14px sans-serif";
            canvas.textAlign = "center";
            canvas.textBaseline = "middle";

            // 绘制表头
            currentX = nameWidth / 2;
            const headerY = cellHeight / 2;
            canvas.fillText("姓名", 40, headerY);

            // 绘制日期
            for (let day = 1; day <= this.daysInMonth; day++) {
              canvas.fillText(String(day), currentX + cellWidth / 2, headerY);
              currentX += cellWidth;
            }

            // 绘制统计列标题
            canvas.fillText("白班", currentX + summaryWidth / 2, headerY);
            currentX += summaryWidth;
            canvas.fillText("早班", currentX + summaryWidth / 2, headerY);
            currentX += summaryWidth;
            canvas.fillText("休息", currentX + summaryWidth / 2, headerY);
            currentX += summaryWidth;
            canvas.fillText("备注", currentX + remarkWidth / 2, headerY);

            // 绘制数据行
            this.selectedStaff.forEach((staff, index) => {
              const rowY = (index + 1.5) * cellHeight;

              // 绘制姓名
              canvas.fillText(staff.name, nameWidth / 2, rowY);

              // 绘制排班数据
              currentX = nameWidth;
              for (let day = 1; day <= this.daysInMonth; day++) {
                const text = this.getShiftText(staff.name, day);
                const shift = this.schedule[`${staff.name}-${day}`];

                // 设置不同班次的背景色
                if (shift) {
                  canvas.fillStyle =
                    shift === "WHITE"
                      ? "#f0f7ff"
                      : shift === "EARLY_NIGHT"
                        ? "#f6ffed"
                        : shift === "NIGHT"
                          ? "#fff7e6"
                          : "#f5f5f5";
                  canvas.fillRect(
                    currentX + 1,
                    (index + 1) * cellHeight + 1,
                    cellWidth - 2,
                    cellHeight - 2,
                  );
                }

                // 设置文字颜色
                canvas.fillStyle =
                  shift === "WHITE"
                    ? "#1890ff"
                    : shift === "EARLY_NIGHT"
                      ? "#52c41a"
                      : shift === "NIGHT"
                        ? "#fa8c16"
                        : "#999999";
                canvas.fillText(text, currentX + cellWidth / 2, rowY);
                currentX += cellWidth;
              }

              // 绘制统计数据
              canvas.fillStyle = "#333333";
              canvas.fillText(
                String(this.getShiftCount(staff.name, "WHITE")),
                currentX + summaryWidth / 2,
                rowY,
              );
              currentX += summaryWidth;
              canvas.fillText(
                String(this.getShiftCount(staff.name, "EARLY_NIGHT")),
                currentX + summaryWidth / 2,
                rowY,
              );
              currentX += summaryWidth;
              canvas.fillText(
                String(this.getRestDaysCount(staff.name)),
                currentX + summaryWidth / 2,
                rowY,
              );
              currentX += summaryWidth;

              // 绘制备注
              const remark = this.getShiftRemark(staff.name);
              canvas.fillText(remark, currentX + remarkWidth / 2, rowY);
            });

            // 绘制完成后输出图片
            canvas.draw(true, () => {
              uni.canvasToTempFilePath({
                canvasId: "scheduleCanvas",
                success: (res) => {
                  uni.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success: () => {
                      uni.showToast({
                        title: "图片已保存到相册",
                        icon: "success",
                      });
                    },
                    fail: (err) => {
                      console.error("保存失败:", err);
                      uni.showToast({
                        title: "保存失败",
                        icon: "error",
                      });
                    },
                  });
                },
                fail: (err) => {
                  console.error("导出失败:", err);
                  uni.showToast({
                    title: "导出失败",
                    icon: "error",
                  });
                },
              });
            });
          })
          .exec();
        // #endif
      } catch (error) {
        console.error("导出图片失败:", error);
        uni.showToast({
          title: "导出失败",
          icon: "error",
        });
      }
    },

    // 修改原有的导出方法
    async exportSchedule() {
      uni.showActionSheet({
        itemList: ["导出为Excel", "导出为图片"],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.exportToExcel();
          } else {
            this.exportAsImage();
          }
        },
      });
    },

    // 将原来的导出逻辑移到这个方法
    exportToExcel() {
      // 准备导出数据
      const data = [
        // 表头
        [
          "姓名",
          ...Array.from({ length: this.daysInMonth }, (_, i) => i + 1),
          "白班",
          "早班",
          "休息",
          "备注",
        ],
      ];

      // 添加每个人的排班数据
      this.selectedStaff.forEach((staff) => {
        const row = [
          staff.name,
          ...Array.from({ length: this.daysInMonth }, (_, i) =>
            this.getShiftText(staff.name, i + 1),
          ),
          this.getShiftCount(staff.name, "WHITE"),
          this.getShiftCount(staff.name, "EARLY_NIGHT"),
          this.getRestDaysCount(staff.name),
          this.getShiftRemark(staff.name),
        ];
        data.push(row);
      });

      let ws, wb, colWidth;

      // #ifdef H5
      // H5环境下使用xlsx导出
      ws = XLSX.utils.aoa_to_sheet(data);
      wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, "排班表");

      // 设置列宽
      colWidth = Array.from({ length: this.daysInMonth + 5 }, (_, i) => {
        if (i === 0) return { wch: 10 }; // 姓名列
        if (i > this.daysInMonth) return { wch: 12 }; // 统计列和备注列
        return { wch: 6 }; // 日期列
      });
      ws["!cols"] = colWidth;

      // 导出文件
      XLSX.writeFile(wb, `排班表${this.currentMonth}.xlsx`);
      // #endif

      // #ifdef MP-WEIXIN
      // 微信小程序环境下，使用微信的文件系统API
      const fileName = `排班表${this.currentMonth}.xlsx`;
      wb = XLSX.utils.book_new();
      ws = XLSX.utils.aoa_to_sheet(data);

      // 设置列宽
      colWidth = Array.from({ length: this.daysInMonth + 5 }, (_, i) => {
        if (i === 0) return { wch: 10 }; // 姓名列
        if (i > this.daysInMonth) return { wch: 12 }; // 统计列和备注列
        return { wch: 6 }; // 日期列
      });
      ws["!cols"] = colWidth;

      XLSX.utils.book_append_sheet(wb, ws, "排班表");

      // 将工作簿写入ArrayBuffer
      const wbout = XLSX.write(wb, {
        bookType: "xlsx",
        type: "array",
      });

      // 创建临时文件路径
      const filePath = `${wx.env.USER_DATA_PATH}/${fileName}`;

      // 写入文件
      const fs = wx.getFileSystemManager();
      try {
        fs.writeFileSync(filePath, wbout, "binary");

        // 保存文件到本地
        wx.saveFileToDisk({
          filePath: filePath,
          success: () => {
            uni.showToast({
              title: "文件已保存",
              icon: "success",
            });
          },
          fail: (err) => {
            console.error("保存文件失败:", err);
            this.fallbackToClipboard(data);
          },
        });
      } catch (err) {
        console.error("写入文件失败:", err);
        this.fallbackToClipboard(data);
      }
      // #endif

      // #ifdef APP-PLUS
      // App环境下使用plus.io API保存文件
      // ... existing APP-PLUS code ...
      // #endif
    },

    // 添加一个回退方法，当文件操作失败时使用剪贴板
    fallbackToClipboard(content) {
      // 准备导出数据
      const data = [
        // 表头
        [
          "姓名",
          ...Array.from({ length: this.daysInMonth }, (_, i) => i + 1),
          "白班",
          "早班",
          "休息",
          "备注",
        ],
      ];

      // 添加每个人的排班数据
      this.selectedStaff.forEach((staff) => {
        const row = [
          staff.name,
          ...Array.from({ length: this.daysInMonth }, (_, i) =>
            this.getShiftText(staff.name, i + 1),
          ),
          this.getShiftCount(staff.name, "WHITE"),
          this.getShiftCount(staff.name, "EARLY_NIGHT"),
          this.getRestDaysCount(staff.name),
          this.getShiftRemark(staff.name),
        ];
        data.push(row);
      });

      // 将数据转换为表格格式的文本
      let textContent = "";
      data.forEach((row) => {
        textContent += row.join("\t") + "\n";
      });

      uni.setClipboardData({
        data: textContent,
        success: () => {
          uni.showModal({
            title: "导出成功",
            content: "排班表已复制到剪贴板，可以粘贴到Excel中查看",
            showCancel: false,
          });
        },
        fail: () => {
          uni.showToast({
            title: "导出失败",
            icon: "error",
          });
        },
      });
    },

    // 导入排班表
    importSchedule() {
      uni.getClipboardData({
        success: (res) => {
          try {
            const scheduleData = JSON.parse(res.data);
            if (
              scheduleData.month &&
              scheduleData.staff &&
              scheduleData.schedule &&
              scheduleData.settings
            ) {
              this.currentMonth = scheduleData.month;
              this.staffList = scheduleData.staff.map((staff) => ({
                name: staff.name,
                selected: true,
              }));
              this.schedule = scheduleData.schedule;
              this.settings = scheduleData.settings;

              uni.showToast({
                title: "排班表导入成功",
                icon: "success",
              });
            } else {
              throw new Error("Invalid schedule data");
            }
          } catch (error) {
            uni.showModal({
              title: "导入失败",
              content: "剪贴板中的数据格式不正确",
              showCancel: false,
            });
          }
        },
      });
    },
    addStaff() {
      if (!this.newStaffName.trim()) return;
      this.staffList.push({
        name: this.newStaffName.trim(),
        selected: true,
      });
      this.newStaffName = "";
    },
    removeStaff(index) {
      this.staffList.splice(index, 1);
    },
    toggleStaff(index) {
      this.staffList[index].selected = !this.staffList[index].selected;
      this.updateAllSelectedState();
    },
    selectAllStaff() {
      const newState = !this.allSelected;
      this.staffList.forEach((staff) => (staff.selected = newState));
      this.allSelected = newState;
    },
    updateAllSelectedState() {
      this.allSelected = this.staffList.every((staff) => staff.selected);
    },
    onMonthChange(e) {
      this.currentMonth = e.detail.value;
    },
    getShiftClass(staffName, day) {
      const shift = this.schedule[`${staffName}-${day}`];
      // 检查是否是指定的休息日
      const [year, month] = this.currentMonth.split("-");
      if (this.isPreferredRestDay(staffName, year, month, day)) {
        return {
          "white-shift": false,
          "early-night-shift": false,
          "night-shift": false,
          "rest-day": true,
        };
      }
      return {
        "white-shift": shift === "WHITE",
        "early-night-shift": shift === "EARLY_NIGHT",
        "night-shift": shift === "NIGHT",
        "rest-day": !shift,
      };
    },
    getShiftText(staffName, day) {
      const shift = this.schedule[`${staffName}-${day}`];
      // 检查是否是指定的休息日
      const [year, month] = this.currentMonth.split("-");
      if (this.isPreferredRestDay(staffName, year, month, day)) {
        return "休";
      }
      if (shift === null) return "休";
      return shift ? this.shiftTypes[shift] : "";
    },
    toggleShift(staffName, day) {
      const currentTime = new Date().getTime();
      const tapGap = currentTime - this.lastTapTime;
      this.lastTapTime = currentTime;

      // 检查是否是指定的休息日
      const [year, month] = this.currentMonth.split("-");
      if (this.isPreferredRestDay(staffName, year, month, day)) {
        uni.showToast({
          title: "指定休息日不可修改",
          icon: "none",
        });
        return;
      }

      // 如果两次点击间隔小于300ms，认为是双击
      if (tapGap < 300) {
        const key = `${staffName}-${day}`;
        const currentShift = this.schedule[key];
        const shifts = ["WHITE", "EARLY_NIGHT", "NIGHT", null];
        const currentIndex = shifts.indexOf(currentShift);
        const nextIndex = (currentIndex + 1) % shifts.length;
        this.$set(this.schedule, key, shifts[nextIndex]);
      }
    },
    generateSchedule() {
      // 重置排班表
      this.schedule = {};
      const selectedStaff = this.selectedStaff;
      const daysInMonth = this.daysInMonth;
      const [year, month] = this.currentMonth.split("-");

      // 初始化每个人的班次统计
      const staffStats = {};
      selectedStaff.forEach((staff) => {
        staffStats[staff.name] = {
          totalShifts: {
            WHITE: 0,
            EARLY_NIGHT: 0,
            NIGHT: 0,
            REST: 0,
          },
        };
      });

      // 计算每个人应该分配的班次数
      const totalDays = daysInMonth;
      const baseShiftsPerPerson = {
        WHITE: Math.floor(totalDays / selectedStaff.length),
        EARLY_NIGHT: Math.floor(totalDays / selectedStaff.length),
        REST: Math.floor(totalDays * 0.25),
      };

      // 根据偏好直接调整目标班次数
      const targetShiftsPerPerson = {};
      selectedStaff.forEach((staff) => {
        const prefs = this.settings.shiftPreferences[staff.name] || {};
        targetShiftsPerPerson[staff.name] = {
          WHITE: Math.max(0, baseShiftsPerPerson.WHITE + (prefs.WHITE || 0)),
          EARLY_NIGHT: Math.max(
            0,
            baseShiftsPerPerson.EARLY_NIGHT + (prefs.EARLY_NIGHT || 0),
          ),
          REST: Math.max(0, baseShiftsPerPerson.REST + (prefs.REST || 0)),
        };
      });

      // 按天分配班次
      for (let day = 1; day <= daysInMonth; day++) {
        // 随机打乱员工顺序
        const shuffledStaff = [...selectedStaff].sort(
          () => Math.random() - 0.5,
        );

        // 先处理指定休息日的员工
        shuffledStaff.forEach((staff) => {
          const restDayPreference = this.getRestDayPreference(staff.name);
          if (restDayPreference.length > 0) {
            const restDay = new Date(restDayPreference[0]).getDate();
            if (
              restDayPreference[0].startsWith(`${year}-${month}`) &&
              restDay === day
            ) {
              this.$set(this.schedule, `${staff.name}-${day}`, null);
              staffStats[staff.name].totalShifts.REST++;
            }
          }
        });

        // 先分配白班和早班
        const dayShifts = {
          WHITE: false,
          EARLY_NIGHT: false,
        };

        // 按照班次数量排序，优先分配给班次少的人
        const sortedForWhite = shuffledStaff
          .filter((staff) => {
            // 检查是否是该员工的指定休息日
            const restDayPreference = this.getRestDayPreference(staff.name);
            if (restDayPreference.length > 0) {
              const restDay = new Date(restDayPreference[0]).getDate();
              if (
                restDayPreference[0].startsWith(`${year}-${month}`) &&
                restDay === day
              ) {
                return false; // 如果是指定休息日，则不参与排班
              }
            }
            return (
              !this.isShiftAvoided(staff.name, "WHITE") &&
              !this.schedule[`${staff.name}-${day}`] &&
              staffStats[staff.name].totalShifts.WHITE <
                targetShiftsPerPerson[staff.name].WHITE + 1 &&
              this.getConsecutiveWorkDays(staff.name, day) < 4
            );
          })
          .sort((a, b) => {
            const aCount = staffStats[a.name].totalShifts.WHITE;
            const bCount = staffStats[b.name].totalShifts.WHITE;
            const aTarget = targetShiftsPerPerson[a.name].WHITE;
            const bTarget = targetShiftsPerPerson[b.name].WHITE;
            const aDiff = aTarget - aCount;
            const bDiff = bTarget - bCount;
            if (aDiff === bDiff) return Math.random() - 0.5;
            return bDiff - aDiff;
          });

        // 分配白班给班次最少的人
        if (sortedForWhite.length > 0) {
          const whiteStaff = sortedForWhite[0];
          this.$set(this.schedule, `${whiteStaff.name}-${day}`, "WHITE");
          dayShifts.WHITE = true;
          staffStats[whiteStaff.name].totalShifts.WHITE++;
        }

        // 分配早班
        const sortedForEarly = shuffledStaff
          .filter((staff) => {
            // 检查是否是该员工的指定休息日
            const restDayPreference = this.getRestDayPreference(staff.name);
            if (restDayPreference.length > 0) {
              const restDay = new Date(restDayPreference[0]).getDate();
              if (
                restDayPreference[0].startsWith(`${year}-${month}`) &&
                restDay === day
              ) {
                return false; // 如果是指定休息日，则不参与排班
              }
            }
            return (
              !this.schedule[`${staff.name}-${day}`] &&
              !this.isShiftAvoided(staff.name, "EARLY_NIGHT") &&
              staffStats[staff.name].totalShifts.EARLY_NIGHT <
                targetShiftsPerPerson[staff.name].EARLY_NIGHT + 1 &&
              this.getConsecutiveWorkDays(staff.name, day) < 4
            );
          })
          .sort((a, b) => {
            const aCount = staffStats[a.name].totalShifts.EARLY_NIGHT;
            const bCount = staffStats[b.name].totalShifts.EARLY_NIGHT;
            const aTarget = targetShiftsPerPerson[a.name].EARLY_NIGHT;
            const bTarget = targetShiftsPerPerson[b.name].EARLY_NIGHT;
            const aDiff = aTarget - aCount;
            const bDiff = bTarget - bCount;
            if (aDiff === bDiff) return Math.random() - 0.5;
            return bDiff - aDiff;
          });

        if (sortedForEarly.length > 0) {
          const earlyStaff = sortedForEarly[0];
          this.$set(this.schedule, `${earlyStaff.name}-${day}`, "EARLY_NIGHT");
          dayShifts.EARLY_NIGHT = true;
          staffStats[earlyStaff.name].totalShifts.EARLY_NIGHT++;
        }

        // 如果没有分配到白班或早班，强制从可用人员中选择
        if (!dayShifts.WHITE || !dayShifts.EARLY_NIGHT) {
          const availableForForced = shuffledStaff.filter((staff) => {
            // 检查是否是该员工的指定休息日
            const restDayPreference = this.getRestDayPreference(staff.name);
            if (restDayPreference.length > 0) {
              const restDay = new Date(restDayPreference[0]).getDate();
              if (
                restDayPreference[0].startsWith(`${year}-${month}`) &&
                restDay === day
              ) {
                return false; // 如果是指定休息日，则不参与排班
              }
            }
            return !this.schedule[`${staff.name}-${day}`];
          });

          if (availableForForced.length > 0) {
            if (!dayShifts.WHITE) {
              const forcedWhiteStaff = availableForForced[0];
              this.$set(
                this.schedule,
                `${forcedWhiteStaff.name}-${day}`,
                "WHITE",
              );
              staffStats[forcedWhiteStaff.name].totalShifts.WHITE++;
            }

            const remainingForEarly = availableForForced.filter(
              (staff) => !this.schedule[`${staff.name}-${day}`],
            );

            if (!dayShifts.EARLY_NIGHT && remainingForEarly.length > 0) {
              const forcedEarlyStaff = remainingForEarly[0];
              this.$set(
                this.schedule,
                `${forcedEarlyStaff.name}-${day}`,
                "EARLY_NIGHT",
              );
              staffStats[forcedEarlyStaff.name].totalShifts.EARLY_NIGHT++;
            }
          }
        }

        // 剩余的人分配晚班或休息
        const remainingStaff = shuffledStaff.filter((staff) => {
          // 检查是否是该员工的指定休息日
          const restDayPreference = this.getRestDayPreference(staff.name);
          if (restDayPreference.length > 0) {
            const restDay = new Date(restDayPreference[0]).getDate();
            if (
              restDayPreference[0].startsWith(`${year}-${month}`) &&
              restDay === day
            ) {
              return false; // 如果是指定休息日，则不参与排班
            }
          }
          return !this.schedule[`${staff.name}-${day}`];
        });

        // 计算当前休息天数的平均值
        const avgRestDays =
          Object.values(staffStats).reduce(
            (sum, stat) => sum + stat.totalShifts.REST,
            0,
          ) / selectedStaff.length;

        // 获取当天已经休息的人数
        const currentDayRestCount = this.getDayRestCount(day);

        // 按照休息天数差异和连续休息情况排序
        const sortedRemainingStaff = remainingStaff.sort((a, b) => {
          const aRestDiff = Math.abs(
            staffStats[a.name].totalShifts.REST - avgRestDays,
          );
          const bRestDiff = Math.abs(
            staffStats[b.name].totalShifts.REST - avgRestDays,
          );
          const aHasConsecutiveRest = this.isConsecutiveRest(a.name, day);
          const bHasConsecutiveRest = this.isConsecutiveRest(b.name, day);
          const aConsecutiveWork = this.getConsecutiveWorkDays(a.name, day);
          const bConsecutiveWork = this.getConsecutiveWorkDays(b.name, day);

          // 优先考虑连续工作天数
          if (aConsecutiveWork > bConsecutiveWork) return -1;
          if (aConsecutiveWork < bConsecutiveWork) return 1;

          // 其次考虑休息天数差异
          if (aRestDiff > bRestDiff) return -1;
          if (aRestDiff < bRestDiff) return 1;

          // 最后考虑连续休息情况
          if (aHasConsecutiveRest && !bHasConsecutiveRest) return 1;
          if (!aHasConsecutiveRest && bHasConsecutiveRest) return -1;

          return Math.random() - 0.5;
        });

        // 确保至少安排2个人休息
        let restCount = currentDayRestCount;
        const needRestCount = 2 - restCount;

        if (needRestCount > 0) {
          // 找出最适合休息的人
          const restCandidates = sortedRemainingStaff.filter(
            (staff) => !this.isConsecutiveRest(staff.name, day),
          );

          // 按需分配休息
          for (
            let i = 0;
            i < Math.min(needRestCount, restCandidates.length);
            i++
          ) {
            const staff = restCandidates[i];
            this.$set(this.schedule, `${staff.name}-${day}`, null);
            staffStats[staff.name].totalShifts.REST++;
            restCount++;
            // 从剩余人员列表中移除已安排休息的人
            const index = sortedRemainingStaff.indexOf(staff);
            if (index > -1) {
              sortedRemainingStaff.splice(index, 1);
            }
          }
        }

        // 剩余人员安排晚班
        sortedRemainingStaff.forEach((staff) => {
          this.$set(this.schedule, `${staff.name}-${day}`, "NIGHT");
          staffStats[staff.name].totalShifts.NIGHT++;
        });
      }
    },
    checkRestRules(staffName, day) {
      let consecutiveWorkDays = 0;
      let consecutiveRestDays = 0;

      // 向前检查
      for (let i = day; i > Math.max(0, day - this.settings.maxWorkDays); i--) {
        const shift = this.schedule[`${staffName}-${i}`];
        if (shift === null) {
          consecutiveRestDays++;
          consecutiveWorkDays = 0;
        } else {
          consecutiveWorkDays++;
          consecutiveRestDays = 0;
        }
      }

      return {
        canWork: consecutiveWorkDays < this.settings.maxWorkDays,
        canRest: consecutiveRestDays < this.settings.minRestDays,
      };
    },
    getShiftCount(staffName, shiftType) {
      let count = 0;
      for (let day = 1; day <= this.daysInMonth; day++) {
        if (this.schedule[`${staffName}-${day}`] === shiftType) {
          count++;
        }
      }
      return count;
    },
    updateShiftPreference(staffName, newPreferences) {
      this.settings.shiftPreferences[staffName] = {
        avoid: newPreferences,
      };
    },
    isShiftAvoided(staffName, shift) {
      const prefs = this.settings.shiftPreferences[staffName];
      return prefs && prefs.avoid && prefs.avoid.includes(shift);
    },
    isEligibleForShift(staffName, shift, day) {
      const previousShift =
        day > 1 ? this.schedule[`${staffName}-${day - 1}`] : null;

      // 不能连续相同班次
      if (previousShift === shift) return false;

      // 检查班次偏好
      if (this.settings.shiftPreferences[staffName]) {
        const prefs = this.settings.shiftPreferences[staffName];
        if (prefs.avoid && prefs.avoid.includes(shift)) return false;
      }

      return true;
    },
    getRestDaysCount(staffName) {
      let count = 0;
      for (let day = 1; day <= this.daysInMonth; day++) {
        if (this.schedule[`${staffName}-${day}`] === null) {
          count++;
        }
      }
      return count;
    },
    isConsecutiveRest(staffName, day) {
      // 检查前一天是否是休息
      const previousDay = day - 1;
      if (previousDay > 0) {
        // 检查前一天是否是指定休息日
        const [year, month] = this.currentMonth.split("-");
        if (this.isPreferredRestDay(staffName, year, month, previousDay)) {
          return true;
        }
        // 检查前一天是否是普通休息日
        return this.schedule[`${staffName}-${previousDay}`] === null;
      }
      return false;
    },
    getDayRestCount(day) {
      let count = 0;
      this.selectedStaff.forEach((staff) => {
        // 检查是否是指定休息日
        const [year, month] = this.currentMonth.split("-");
        if (this.isPreferredRestDay(staff.name, year, month, day)) {
          count++;
          return;
        }
        if (this.schedule[`${staff.name}-${day}`] === null) {
          count++;
        }
      });
      return count;
    },
    getShiftPreference(staffName, shiftType) {
      if (!this.settings.shiftPreferences[staffName]) {
        this.settings.shiftPreferences[staffName] = {
          WHITE: 0,
          EARLY_NIGHT: 0,
          REST: 0,
        };
      }
      return this.settings.shiftPreferences[staffName][shiftType] || 0;
    },
    adjustShiftPreference(staffName, shiftType, delta) {
      if (!this.settings.shiftPreferences[staffName]) {
        this.settings.shiftPreferences[staffName] = {
          WHITE: 0,
          EARLY_NIGHT: 0,
          REST: 0,
        };
      }
      const currentValue =
        this.settings.shiftPreferences[staffName][shiftType] || 0;
      // 限制调整范围在 -3 到 3 之间
      const newValue = Math.max(-3, Math.min(3, currentValue + delta));
      this.$set(this.settings.shiftPreferences[staffName], shiftType, newValue);
    },
    getShiftRemark(staffName) {
      // 获取所有人的班次数统计
      const allShifts = this.selectedStaff.map((staff) => ({
        name: staff.name,
        white: this.getShiftCount(staff.name, "WHITE"),
        early: this.getShiftCount(staff.name, "EARLY_NIGHT"),
        rest: this.getRestDaysCount(staff.name),
      }));

      // 获取各类班次的众数（出现次数最多的数字）
      const getModeValue = (arr) => {
        const frequency = {};
        let maxFreq = 0;
        let modeValue;

        arr.forEach((value) => {
          frequency[value] = (frequency[value] || 0) + 1;
          if (frequency[value] > maxFreq) {
            maxFreq = frequency[value];
            modeValue = value;
          }
        });

        return modeValue;
      };

      // 计算各类班次的众数
      const modeShifts = {
        WHITE: getModeValue(allShifts.map((s) => s.white)),
        EARLY_NIGHT: getModeValue(allShifts.map((s) => s.early)),
        REST: getModeValue(allShifts.map((s) => s.rest)),
      };

      // 获取当前员工的实际班次数
      const actualShifts = {
        WHITE: this.getShiftCount(staffName, "WHITE"),
        EARLY_NIGHT: this.getShiftCount(staffName, "EARLY_NIGHT"),
        REST: this.getRestDaysCount(staffName),
      };

      // 获取员工的偏好设置
      const prefs = this.settings.shiftPreferences[staffName] || {};

      // 计算差异并生成备注
      const remarks = [];

      // 白班差异
      const whiteDiff = actualShifts.WHITE - modeShifts.WHITE;
      if (prefs.WHITE < 0 && whiteDiff >= 0) {
        remarks.push(`白多${Math.abs(prefs.WHITE)}`);
      } else if (prefs.WHITE > 0 && whiteDiff <= 0) {
        remarks.push(`白少${prefs.WHITE}`);
      } else if (!prefs.WHITE) {
        // 没有偏好设置时，显示正常差异
        if (whiteDiff > 0) {
          remarks.push(`白多${whiteDiff}`);
        } else if (whiteDiff < 0) {
          remarks.push(`白少${Math.abs(whiteDiff)}`);
        }
      }

      // 早班差异
      const earlyDiff = actualShifts.EARLY_NIGHT - modeShifts.EARLY_NIGHT;
      if (prefs.EARLY_NIGHT < 0 && earlyDiff >= 0) {
        remarks.push(`早多${Math.abs(prefs.EARLY_NIGHT)}`);
      } else if (prefs.EARLY_NIGHT > 0 && earlyDiff <= 0) {
        remarks.push(`早少${prefs.EARLY_NIGHT}`);
      } else if (!prefs.EARLY_NIGHT) {
        // 没有偏好设置时，显示正常差异
        if (earlyDiff > 0) {
          remarks.push(`早多${earlyDiff}`);
        } else if (earlyDiff < 0) {
          remarks.push(`早少${Math.abs(earlyDiff)}`);
        }
      }

      // 休息差异
      const restDiff = actualShifts.REST - modeShifts.REST;
      if (prefs.REST < 0 && restDiff >= 0) {
        remarks.push(`休多${Math.abs(prefs.REST)}`);
      } else if (prefs.REST > 0 && restDiff <= 0) {
        remarks.push(`休少${prefs.REST}`);
      } else if (!prefs.REST) {
        // 没有偏好设置时，显示正常差异
        if (restDiff > 0) {
          remarks.push(`休多${restDiff}`);
        } else if (restDiff < 0) {
          remarks.push(`休少${Math.abs(restDiff)}`);
        }
      }

      return remarks.join("，");
    },
    getConsecutiveWorkDays(staffName, day) {
      let count = 0;
      // 向前检查连续工作天数
      for (let i = day - 1; i > Math.max(0, day - 10); i--) {
        // 检查是否是指定休息日
        const [year, month] = this.currentMonth.split("-");
        if (this.isPreferredRestDay(staffName, year, month, i)) {
          break;
        }
        const shift = this.schedule[`${staffName}-${i}`];
        if (shift === null) {
          break;
        }
        count++;
      }
      return count;
    },
    getRestDayPreference(staffName) {
      if (!this.settings.restDayPreferences) {
        this.settings.restDayPreferences = {};
      }
      if (!this.settings.restDayPreferences[staffName]) {
        this.settings.restDayPreferences[staffName] = [];
      }
      return this.settings.restDayPreferences[staffName];
    },
    setRestDayPreference(staffName, value) {
      if (!this.settings.restDayPreferences) {
        this.settings.restDayPreferences = {};
      }
      if (!this.settings.restDayPreferences[staffName]) {
        this.settings.restDayPreferences[staffName] = [];
      }
      // 检查是否已经存在这个日期
      if (!this.settings.restDayPreferences[staffName].includes(value)) {
        this.settings.restDayPreferences[staffName].push(value);
        // 按日期排序
        this.settings.restDayPreferences[staffName].sort();
      }
    },
    clearRestDayPreference(staffName, date) {
      if (!this.settings.restDayPreferences) {
        this.settings.restDayPreferences = {};
      }
      if (this.settings.restDayPreferences[staffName]) {
        const index = this.settings.restDayPreferences[staffName].indexOf(date);
        if (index > -1) {
          this.settings.restDayPreferences[staffName].splice(index, 1);
        }
      }
    },
    isPreferredRestDay(staffName, year, month, day) {
      if (!this.settings.restDayPreferences) {
        this.settings.restDayPreferences = {};
      }
      const restDays = this.settings.restDayPreferences[staffName] || [];
      if (!Array.isArray(restDays)) {
        return false;
      }
      return restDays.some((date) => {
        if (!date) return false;
        const [y, m] = date.split("-");
        const d = new Date(date).getDate();
        return y === year && m === month && d === day;
      });
    },
  },
};
</script>

<style>
.schedule-container {
  padding: 20rpx;
}

.staff-pool {
  margin-bottom: 30rpx;
  border: 1px solid #eee;
  padding: 20rpx;
  border-radius: 10rpx;
}

.pool-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
}

.staff-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20rpx;
}

.staff-item {
  display: flex;
  align-items: center;
  gap: 10rpx;
  background: #f5f5f5;
  padding: 10rpx 20rpx;
  border-radius: 6rpx;
}

.delete {
  color: #ff4d4f;
  margin-left: 10rpx;
  cursor: pointer;
}

.schedule-table {
  border: 1px solid #ddd;
  overflow-x: auto;
  width: 100%;
  white-space: nowrap;
  margin-top: 20rpx;
  background: #fff;
  position: relative;
}

.table-tip {
  font-size: 24rpx;
  color: #666;
  margin-bottom: 10rpx;
  padding: 10rpx;
  background: #f9f9f9;
  border-radius: 4rpx;
}

.table-header {
  display: flex;
  background: #f5f5f5;
  position: sticky;
  top: 0;
  z-index: 3;
}

.header-cell {
  min-width: 120rpx;
  width: 120rpx;
  padding: 20rpx 10rpx;
  text-align: center;
  border-right: 1px solid #ddd;
  font-weight: bold;
  flex-shrink: 0;
  background: #f5f5f5;
}

.name-cell {
  min-width: 120rpx;
  width: 120rpx;
  padding: 20rpx 10rpx;
  text-align: center;
  border-right: 1px solid #ddd;
  font-weight: bold;
  flex-shrink: 0;
  background: #f5f5f5;
  position: sticky;
  left: 0;
  z-index: 2;
}

.table-row {
  display: flex;
  border-top: 1px solid #ddd;
  position: relative;
}

.table-row:nth-child(even) .name-cell {
  background: #fafafa;
}

.day-cell,
.schedule-cell {
  min-width: 80rpx;
  width: 80rpx;
  padding: 20rpx 10rpx;
  text-align: center;
  border-right: 1px solid #ddd;
  flex-shrink: 0;
}

.summary-cell {
  min-width: 80rpx;
  width: 80rpx;
  padding: 20rpx 10rpx;
  text-align: center;
  border-right: 1px solid #ddd;
  background: #f5f5f5;
  font-weight: bold;
  flex-shrink: 0;
}

.white-shift {
  background: #f0f7ff !important;
  color: #1890ff;
}

.early-night-shift {
  background: #f6ffed !important;
  color: #52c41a;
}

.night-shift {
  background: #fff7e6 !important;
  color: #fa8c16;
}

.rest-day {
  background: #f5f5f5 !important;
  color: #999;
}

.schedule-cell {
  cursor: pointer;
  transition: all 0.3s;
  user-select: none; /* 防止双击时选中文字 */
}

.schedule-cell:hover {
  opacity: 0.8;
}

.schedule-cell:active {
  opacity: 0.6;
}

.btn-generate {
  margin-top: 30rpx;
  background: #1890ff;
  color: #fff;
  border: none;
  padding: 20rpx 40rpx;
  border-radius: 6rpx;
}

.schedule-settings {
  margin: 20rpx 0;
  padding: 20rpx;
  background: #f9f9f9;
  border-radius: 10rpx;
}

.settings-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
  padding-bottom: 20rpx;
  border-bottom: 1px solid #eee;
}

.settings-actions {
  display: flex;
  gap: 10rpx;
}

.btn-action {
  font-size: 24rpx;
  padding: 10rpx 20rpx;
  background: #f0f0f0;
  border: none;
  border-radius: 4rpx;
  color: #333;
}

.btn-action:active {
  background: #e0e0e0;
}

.setting-item {
  display: flex;
  align-items: center;
  margin-bottom: 20rpx;
}

.setting-label {
  min-width: 200rpx;
}

.setting-value {
  flex: 1;
  display: flex;
  align-items: center;
}

.input-number {
  width: 100rpx;
  text-align: center;
  margin: 0 10rpx;
  padding: 4rpx 10rpx;
  border: 1px solid #ddd;
  border-radius: 4rpx;
}

.btn-generate:active {
  background: #096dd9;
}

.error-message {
  color: #ff4d4f;
  font-size: 24rpx;
  margin-top: 10rpx;
}

.success-message {
  color: #52c41a;
  font-size: 24rpx;
  margin-top: 10rpx;
}

.staff-preferences {
  margin: 20rpx 0;
  padding: 30rpx;
  background: #ffffff;
  border-radius: 12rpx;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
}

.preferences-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
  padding-bottom: 20rpx;
  border-bottom: 1px solid #f0f0f0;
}

.preferences-title {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.title-text {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.preferences-tip {
  font-size: 24rpx;
  color: #999;
  font-weight: normal;
}

.btn-toggle {
  display: flex;
  align-items: center;
  gap: 6rpx;
  font-size: 26rpx;
  padding: 12rpx 24rpx;
  background: #f5f7fa;
  border: none;
  border-radius: 6rpx;
  color: #666;
  transition: all 0.3s;
}

.btn-toggle:active {
  background: #e8eaed;
}

.toggle-icon {
  font-size: 20rpx;
  margin-left: 4rpx;
}

.preferences-list {
  display: flex;
  flex-direction: column;
  gap: 24rpx;
}

.preference-item {
  background: #f9fafc;
  padding: 24rpx;
  border-radius: 8rpx;
  border: 1px solid #f0f0f0;
}

.staff-name {
  font-size: 28rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 16rpx;
  display: block;
}

.shift-preferences {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.shift-row {
  display: flex;
  gap: 32rpx;
  flex-wrap: wrap;
}

.shift-preference-item {
  display: flex;
  align-items: center;
  gap: 12rpx;
  min-width: 200rpx;
}

.shift-label {
  font-size: 26rpx;
  color: #666;
  min-width: 50rpx;
}

.stepper {
  display: flex;
  align-items: center;
  border: 1px solid #e8e8e8;
  border-radius: 6rpx;
  overflow: hidden;
  background: #fff;
}

.stepper-btn {
  width: 64rpx;
  height: 56rpx;
  line-height: 56rpx;
  text-align: center;
  background: #fafafa;
  border: none;
  padding: 0;
  margin: 0;
  font-size: 28rpx;
  color: #666;
  transition: all 0.3s;
}

.stepper-btn.minus {
  border-right: 1px solid #e8e8e8;
}

.stepper-btn.plus {
  border-left: 1px solid #e8e8e8;
}

.stepper-btn:active {
  background: #f0f0f0;
}

.stepper-value {
  width: 80rpx;
  height: 56rpx;
  line-height: 56rpx;
  text-align: center;
  background: #fff;
  font-size: 28rpx;
  color: #999;
}

.stepper-value.has-value {
  color: #1890ff;
  font-weight: 500;
}

.add-staff {
  margin-top: 20rpx;
  display: flex;
  gap: 20rpx;
  align-items: center;
}

.staff-input {
  flex: 1;
  height: 70rpx;
  padding: 0 30rpx;
  border: 2rpx solid #e8e8e8;
  border-radius: 8rpx;
  font-size: 28rpx;
  background: #fff;
  transition: all 0.3s;
}

.staff-input:focus {
  border-color: #1890ff;
  box-shadow: 0 0 0 2rpx rgba(24, 144, 255, 0.1);
}

.input-placeholder {
  color: #bfbfbf;
}

.btn-add {
  height: 70rpx;
  line-height: 70rpx;
  padding: 0 40rpx;
  border: none;
  border-radius: 8rpx;
  background: #1890ff;
  color: #fff;
  font-size: 28rpx;
  transition: all 0.3s;
}

.btn-add:active {
  background: #096dd9;
}

.remark-cell {
  min-width: 200rpx;
  width: 200rpx;
  text-align: left;
  padding: 20rpx;
  white-space: normal;
  word-break: break-all;
}

.rest-days-container {
  display: flex;
  flex-direction: column;
  gap: 10rpx;
  flex: 1;
}

.rest-days-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10rpx;
}

.rest-day-item {
  display: flex;
  align-items: center;
  gap: 6rpx;
  background: #f0f7ff;
  padding: 4rpx 12rpx;
  border-radius: 4rpx;
  font-size: 24rpx;
}

.delete-rest-day {
  color: #ff4d4f;
  font-size: 24rpx;
  padding: 0 4rpx;
  cursor: pointer;
}

.rest-day-picker {
  margin-top: 10rpx;
}

.picker-value {
  height: 60rpx;
  line-height: 60rpx;
  padding: 0 20rpx;
  border: 1px dashed #d9d9d9;
  border-radius: 4rpx;
  color: #666;
  font-size: 24rpx;
  text-align: center;
}
</style>
